共计 7172 个字符,预计需要花费 18 分钟才能阅读完成。
引入
我们在开发一个网页的时候, 无可避免的需要设计实现网站的用户系统; 此时我们需要实现包括用户注册、用户登录、用户认证、注销、修改密码等功能, 为了节省这个麻烦的过程, Django 自带了强大的用户认证系统 Auth, 它默认使用auth_user 表来存储用户的数据
ps : auth 本质上也是一个 app
一.Auth 模块的使用于字段
1. 先导入 auth 模块
form django.contrib import auth
2. 进行数据迁移命令来生成 auth_user 表
python3 manage.py makemigrations
python3 manage.py migrate
3.auth_user 表字段
- auth_user 默认有 11 个字段
字段 | 释义 |
---|---|
id | ID |
password | 密码 |
last_login | 最后登录时间 |
is_superuser | 是否是管理员 |
username | 用户名 |
first_name | 姓 |
last_name | 名 |
邮箱 | |
is_staff | 是否是工作人员 |
is_active | 是否激活 |
date_joined | 创建时间 |
二. 常用方法
1.authenticated : 登入认证
- 作用 : 提供了用户认证功能,即验证用户名以及密码是否正确
-
必须传入两个参数 : username & password
-
校验成功返回 True, 校验失败返回 None
- request 可以不用传, 默认就是 None
from django.contrib import auth
user_obj = auth.authenticated(request, username=username, password=password)
if user_obj:
print(user_obj.username)
print(user_obj.password)
else:
print('校验失败')
2.login : 保存用户状态
- 作用 : 该函数接收一个 HttpRequest 对象,以及一个经过认证的 User 对象
- 实现一个用户登录的功能, 本质上会在后端为该用户生成相关 session 数据存在 session 表中
- 只要执行了该方法 你就可以在任何地方通过 request.user 获取到当前登陆的用户对象, 否则拿到的是一个匿名用户对象
# 登入成功后调用
auth.login(request, user_obj) # 内部调用的就是 request.session['key']=user_obj
3.logout : 退出登入
- 作用 : 该函数接受一个 HttpRequest 对象,无返回值
- 当调用该函数时, 当前请求的 session 信息会全部清除; 该用户即使没有登录, 使用该函数也不会报错
# 注销当前登录用户:
auth.logout(request) # 内部使用的就是 request.session.flush()
4.is_authenticated : 判断用户是否登入
- 用来判断当前请求是否通过了认证
# 视图类中使用
if not request.user.is_authenticated():
print('未登入, 请先登入')
# 模板中使用
{% if request.user.is_authenticated %}
{{request.user.username}} 欢迎回家
{% else %}
<a href="/auth_login/"> 请去登录 </a>
{% endif %}
5.login_required : 登入认证装饰器
- 作用 : 一个装饰器工具, 用来快捷的给某个视图添加登录校验
# 使用方式一 : 直接在视图函数上添加
@login_required(login_url='/login/') # 需要指定 url(因为它存在默认 url)
def logout_func(request):
auth.logout(request)
return redirect("/login/")
# 使用方式二 : 在配置文件中全局配置
LOGIN_URL = '/login/'
6.create_user : 创建普通用户
- 作用 : 提供的一个创建新用户的方法, 需要提供必要参数 username & password 等
from django.contrib.auth.models import User
user = User.objects.create_user(username='用户名',password='密码',email='邮箱',...)
7.create_superuser : 创建管理员用户
- 作用 : 提供的一个创建管理员用户的方法, 需要提供必要参数 username & password & email 等
from django.contrib.auth.models import User
user = User.objects.create_superuser(username='用户名',password='密码',email='邮箱',...)
8.check_password : 检验密码
- 作用 : 提供的一个检查密码是否正确的方法, 需要提供当前请求用户的密码
- 密码正确返回 True, 否则返回 False
if user.check_password('[你的密码]'):
print('ok')
9.set_password : 修改密码
-
作用 : 提供的一个修改密码的方法, 接收要设置的新密码作为参数
-
设置完一定要调用用户对象的 save 方法
user.set_password(password='[新密码]')
user.save() # 保存
三. 补充 User 对象属性
User.username # 获取用户名
User.password # 获取密码
User.is_staff # 判断用户是否拥有网站的管理权限, 如果没有, 后台 admin 登录不进去
User.is_active # 判断是否允许用户登录, 设置为 False, 可以在不删除用户的前提下禁止用户登录
User.is_superuser # 判断是否是超级管理员
四. auth_user 表扩展字段
auth_user 中的字段有限, 想要在 auth_user 表中添加新的字段, 我们可以对其进行扩展
1. 扩展方式一 : 建立一对一外键关系
- 新建一个模型类, 比如要添加 Phone 字段, 在该模型内中写入, 并添加 User 的外键字段
from django.contrib.auth.models import User
class user_detail(models.Model):
user=models.OneToOneField(to='User')
phone=models.CharField(max_length=32)
2. 扩展方式二 : 继承 AbstractUser 类来扩写 (步骤)
- 首先大前提是没有生成 auth_user 表(也就是没进行数据库迁移操作)(有的话需要删干净迁移记录和表)
- 书写一个类, 并继承 AbstractUser 类
- 在类中可以书写你需要扩展的字段, 也可以重写原来的字段
class MyAuthUser(AbstractUser):
username=models.CharField(max_length=12) # 重写字段
phone=models.CharField(max_length=32) # 书写新字段
- 到 setting.py 配置文件中设置 AUTH_USER_MODEL 参数, 不然报错
AUTH_USER_MODEL = "[app 名].[类名]"
AUTH_USER_MODEL = "app01.MyAuthUser" # 示例
- 最后进行数据库迁移命令
python3 manage.py makemigrations
python3 manage.py migrate
3. 如果 auth_user 表已经存在
- 先删库
- 并清空项目中所有的 makemigrations 而来的迁移记录
- 再清空源码中 admin,auth 俩 app 的 makemigrations 产生的记录
五. 基于 Auth 模块示例
1. 需求
- 基于 auth 继承 AbstractUser 类,加一个 phone 字段(也可以加多其它)
- 实现用户的注册登录,登录成功,在 home 页面显示用户名,未登录,则跳转登入界面
- 超级管理员能够禁用户登录, 实现用户退出功能
2. 代码示例
- 扩写 auth_user 表
from django.db import models
from django.contrib.auth.models import AbstractUser
class AuthUser(AbstractUser):
phone = models.CharField(max_length=32) # 电话
is_display = models.BooleanField(default=False) # 自定义的用户是否锁定
- 路由层 urls.py 文件
from django.contrib import admin
from django.urls import path,re_path
from app01 import views
urlpatterns = [path('admin/', admin.site.urls),
path('login/', views.login_auth),
path('register/', views.register),
path('home/', views.home),
path('logout/', views.logout_func,name='logout_name'),
path('admin_user/', views.admin_func,name='admin_name'),
re_path('^lock/', views.lock,name='lock_name'),
re_path('^unlock/', views.unlock,name='unlock_name'),
]
- 视图层 views.py 文件
from django.shortcuts import render, HttpResponse, redirect
from django.http import JsonResponse
from app01.models import AuthUser
from django.contrib import auth
from django.contrib.auth.decorators import login_required
from django.core.paginator import Paginator
# 登入
def login_auth(request):
if request.method == "GET":
return render(request, 'login.html')
if request.method == "POST":
name = request.POST.get('name')
passwd = request.POST.get('passwd')
res = AuthUser.objects.filter(username=name).first()
if res:
user_obj = auth.authenticate(request, username=name, password=passwd)
if user_obj:
# 判断是否是锁定状态
if user_obj.is_display:
auth.login(request, user_obj)
goto_url = request.GET.get('goto')
if goto_url:
return JsonResponse({'url': goto_url})
else:
return JsonResponse({'url': '/home/'})
return JsonResponse({'tag': 100, 'error': '用户被锁定, 请联系管理员'})
return JsonResponse({'tag': 100, 'error': '密码错误'})
return JsonResponse({'tag': 100, 'error': '该用户未注册'})
# 注册
def register(request):
if request.method == 'GET':
return render(request, 'register.html')
elif request.method == "POST":
name = request.POST.get('name')
passwd = request.POST.get('passwd')
re_passwd = request.POST.get('re_passwd')
phone = request.POST.get('phone')
res = AuthUser.objects.filter(username=name).first()
# 判断是否存在该用户
if not res:
if passwd == re_passwd:
user = AuthUser.objects.create_user(username=name, password=passwd, phone=phone, is_display=True)
success = {'tag': 200, 'name': f" 用户名 : {name}"}
return JsonResponse(success)
else:
info = {'tag': 400, 'error': '两次密码不一致'}
return JsonResponse(info)
return JsonResponse({'tag': 400, 'error': '用户名已存在'})
# home 页面
@login_required(login_url='/login/')
def home(request):
if request.method == "GET":
name = request.user.username
return render(request, "home.html", locals())
# 注销登入
@login_required(login_url='/login/')
def logout_func(request):
auth.logout(request)
return redirect("/login/")
# admin 页面
@login_required(login_url='/login/')
def admin_func(request):
if request.method == "GET":
return render(request, 'admin_user.html')
# 分页模板
@login_required(login_url='/login/')
def admin_func(request):
# 🔰1. 分页后的 paginator 对象
current_page = int(request.GET.get('page_num', 1)) # 获取用户点击的页码, 没有则默认第一页
shop_list = AuthUser.objects.all() # 获取所有的商品对象列表
paginator = Paginator(shop_list, 5)
# 🔰2. 页码列表
if paginator.num_pages > 9:
if current_page - 4 < 1:
page_range = range(1, 10)
elif current_page + 4 > paginator.num_pages: page_range = range(paginator.num_pages - 8, paginator.num_pages + 1)
else:
page_range = range(current_page - 4, current_page + 4)
else:
page_range = paginator.page_range
# 🔰3.page 对象
try:
page = paginator.page(current_page)
except Exception as E:
page = paginator.page(current_page)
return render(request, 'admin_user.html', {'page_range': page_range, 'page': page, 'current_page': current_page})
# 加锁
def lock(request):
if request.method == "POST":
nid = request.POST.get('nid')
print(nid)
# 判断是否是管理员
if request.user.is_superuser:
if request.user.username == AuthUser.objects.filter(id=nid).first().username:
return JsonResponse({'tag': 100, 'info': '不能锁定自己'})
else:
AuthUser.objects.filter(id=nid).update(is_display=False)
return JsonResponse({'tag': 101, 'info': '锁定成功'})
data = {'tag': 100, 'info': '你不是管理员用户'}
return JsonResponse(data)
# 解锁
def unlock(request):
if request.method == "POST":
nid = request.POST.get('nid')
print(nid)
if request.user.is_superuser:
AuthUser.objects.filter(id=nid).update(is_display=True)
return JsonResponse({'tag': 101, 'info': '解锁成功'})
return JsonResponse({'tag': 100, 'info': '你不是管理员用户'})
3. 效果展示
- 注册密码 失败 & 成功
- 登入 失败 & 成功
- 超级管理员进行锁定以及解锁, 非管理员无法进行操作
正文完